package nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
import java.util.Set;

/**
 * nio服务器端
 *
 * @author jack.wu
 * @version 1.0
 * @date 2020-05-14
 */
public class NioServer {

    public static void main(String[] args) throws IOException {

        // 1、创建ServerSocketChannel 类似于bio 中的ServerSocket
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();

        // 2、得到一个Selector
        Selector selector = Selector.open();

        // 3、绑定一个端口，在服务器进行监听
        serverSocketChannel.bind(new InetSocketAddress(6666));
        // 设置为非阻塞
        serverSocketChannel.configureBlocking(false);

        // 4、把ServerSocketChannel注册到Selector上并指定关心事件
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

        while (true) {

            if (selector.select(1000) == 0) {
                System.out.println("服务器等待了一秒，无连接~~~");
                continue;
            }
            Set<SelectionKey> selectionKeys = selector.selectedKeys();
            Iterator<SelectionKey> keyIterator = selectionKeys.iterator();

            while (keyIterator.hasNext()) {
                SelectionKey item = keyIterator.next();
                // 处理连接事件
                if (item.isAcceptable()) {
                    // 为该客户端生成一个SocketChannel
                    SocketChannel socketChannel = serverSocketChannel.accept();
                    socketChannel.configureBlocking(false);
                    // 将SocketChannel注册到Selector，并设置关心事件，同时指定一个Buffer
                    socketChannel.register(selector, SelectionKey.OP_READ, ByteBuffer.allocate(1024));
                    System.out.println("建立连接~~~");
                }

                // 处理读取事件
                if (item.isReadable()) {
                    SocketChannel channel = (SocketChannel) item.channel();
                    ByteBuffer buffer = (ByteBuffer) item.attachment();
                    channel.read(buffer);
                    System.out.println("从客户端 " + new String(buffer.array()));
                }

                // 手动从集合中删除当前的SelectionKey，防止重复操作
                keyIterator.remove();
            }
        }
    }

}
